home *** CD-ROM | disk | FTP | other *** search
/ L' Effet Pommier 3 / L'Effet Pommier - Volume 03.iso / Programmation / gray image 2.1 / filter.h < prev    next >
Text File  |  1995-05-31  |  7KB  |  231 lines

  1. // This may look like C code, but it is really -*- C++ -*-
  2. /*
  3.  ************************************************************************
  4.  *
  5.  *           Grayscale Image Filtration
  6.  *
  7.  * Declaration of functions/procedures (generally grouped together
  8.  * under the FilterIt class umbrella) that do linear and some non-linear
  9.  * image filtration and related transfromations. Most of the operations
  10.  * do filtration "inplace"
  11.  *
  12.  * Note that class FilterIt is a friend of IMAGE, so it's privy of
  13.  * IMAGE internals and can use them to make processing faster.
  14.  *
  15.  * $Id: filter.h,v 2.0 1995/03/18 18:15:48 oleg Exp oleg $
  16.  *
  17.  ************************************************************************
  18.  */
  19.  
  20. #ifndef __GNUC__
  21. #pragma once
  22. #endif
  23. #ifndef _filter_h
  24. #define _filter_h
  25.  
  26. #ifdef __GNUC__
  27. #pragma interface
  28. #endif
  29.  
  30. #include "image.h"
  31. #include "std.h"
  32.  
  33. /*
  34.  *------------------------------------------------------------------------
  35.  *             Convolution kernels
  36.  *
  37.  * Kernel coeffs are stored as rational numbers with some common denominator,
  38.  * which can be either 1 (that is, all coeffs are ints) or power of two, or
  39.  * some arbitrary card number. We use a family of CommonDenom classes for each
  40.  * of those situations. Each members of the family defines how to
  41.  * execute a division of long int by a denominator most efficiently.
  42.  * The classes are then used in "templates" in actual filtration algorithm
  43.  */
  44.  
  45. class CommonDenomOne
  46. {
  47. public:
  48.   inline int divide(long int x)    const { return x; }
  49. };
  50.  
  51. class over_2_up
  52. {
  53.   card exponent;
  54. public:
  55.   over_2_up(const card _exp) : exponent(_exp) {}
  56.   inline int divide(long int x)    const { return x>>exponent; }
  57. };
  58.  
  59. class CommonDenom
  60. {
  61.   card denom;
  62. public:
  63.   CommonDenom(const card _denom) : denom(_denom) {}
  64.   inline int divide(long int x)    const { return x/(signed)denom; }
  65. };
  66.                 // 1D 3-point convolution kernel
  67. template <class Denom>
  68. class ConvKernel3
  69. {
  70.   const int am1,a0,ap1;        // a[k-1], a[k], a[k+1] coeffs
  71.   const Denom common_denominator;
  72. public:
  73.   ConvKernel3(const int _am1, const int _a0, const int _ap1,
  74.           const Denom denom) :
  75.     am1(_am1), a0(_a0), ap1(_ap1), common_denominator(denom) {}
  76.   inline int convolve(const GRAY_SIGNED pm1, const GRAY_SIGNED p0,
  77.               const GRAY_SIGNED pp1) const
  78.   { return common_denominator.divide(pm1*am1 + p0*a0 + pp1*ap1); }
  79. };
  80.  
  81.                 // Expand templates right here...
  82. //template class ConvKernel3<CommonDenomOne>;
  83.  
  84.                 // Convolution kernels
  85.                     // all coeffs integers
  86. inline ConvKernel3<CommonDenomOne> conv_kernel(
  87.     const int am1, const int a0, const int ap1)
  88. { return ConvKernel3<CommonDenomOne>(am1,a0,ap1,CommonDenomOne()); }
  89.  
  90. inline ConvKernel3<over_2_up>
  91. conv_kernel(const int am1, const int a0, const int ap1, over_2_up denom)
  92. { return ConvKernel3<over_2_up>(am1,a0,ap1,denom); }
  93.  
  94. inline ConvKernel3<CommonDenom>
  95. conv_kernel(const int am1, const int a0, const int ap1, CommonDenom denom)
  96. { return ConvKernel3<CommonDenom>(am1,a0,ap1,denom); }
  97.  
  98.  
  99. /*
  100.  *------------------------------------------------------------------------
  101.  *                 Look-up tables
  102.  * to specify a mapping operation GRAY -> GRAY
  103.  */
  104.  
  105. class LookupT
  106. {
  107.   friend class FilterIt;
  108.  
  109.   GRAY min_val, max_val;        // in the GRAY domain of the mapping
  110.   GRAY * table;                // mapping itself
  111.   card no_entries;            // in the table
  112.  
  113.                     // init the LookupT but don't fill in
  114.                     // the table
  115.   void allocate(const GRAY _min_val, const GRAY _max_val);
  116.  
  117.   enum { Preallocated_no = 256 };    // Allocate ahead that many entries
  118.   GRAY preallocated [Preallocated_no];
  119.  
  120. public:
  121.                 // What to do with pixels that outside
  122.                 // [min_val,max_val] when doing mapping
  123.   enum FringeHandling { CoerceFringes, LeaveFringes };
  124.  
  125.                 // Just to make constructing some common
  126.                 // look-up tables sweeter...
  127.   struct Identical { const card depth; Identical(const card _d) : depth(_d){}};
  128.   struct MapTo {
  129.     const GRAY from, to;
  130.     MapTo(const GRAY _from, const GRAY _to) : from(_from), to(_to) {}
  131.   };
  132.   struct DownGRAY {
  133.     const card depth_from, depth_to;
  134.     DownGRAY(const card _f, const card _t) : depth_from(_f), depth_to(_t) {}
  135.   };
  136.  
  137.  
  138.                 // Identical pixel mapping for an image of
  139.                 // specified depth
  140.   LookupT(const Identical id);
  141.  
  142.                 // Build a table (with one entry) to map
  143.                 // just one particular pixel
  144.   LookupT(const MapTo map_one);
  145.  
  146.                 // Build a table to reduce image depth from
  147.                 // one value to another (that is, build a
  148.                 // stripy table)
  149.   LookupT(const DownGRAY downgray);
  150.  
  151.   LookupT(const LookupT& another);    // standard assignment stuff
  152.   LookupT& operator= (const LookupT& another);
  153.   ~LookupT(void);
  154.  
  155.                 // Getting hold of and/or modifying
  156.                 // specific mappings
  157.   GRAY& operator[] (const GRAY val);
  158.   GRAY  operator[] (const GRAY val) const;
  159.  
  160.                 // Convolve two Lookup tables, that is,
  161.                 // translate pixels of this according to
  162.                 // another table
  163.                 // (Lookup table composition)
  164.   LookupT& apply(const LookupT& another,
  165.          const FringeHandling fringe_handling);
  166.  
  167.   GRAY q_min(void) const    { return min_val; }
  168.   GRAY q_max(void) const    { return max_val; }
  169. };
  170.  
  171. inline GRAY& LookupT::operator[] (const GRAY val)
  172. {
  173.   if( val < min_val || val > max_val )
  174.     _error("The pixel value %d to look up is out of range [%d,%d]",
  175.        val,min_val,max_val);
  176.   return table[val-min_val];
  177. }
  178.  
  179. inline GRAY  LookupT::operator[] (const GRAY val) const
  180. { return (*(LookupT *)this)[val]; }
  181.  
  182. /*
  183.  *------------------------------------------------------------------------
  184.  *             The umbrella class FilterIt itself
  185.  *
  186.  */
  187.  
  188. class FilterIt
  189. {
  190.   IMAGE& image;                // Image under filtration
  191.  
  192.   void operator=(const FilterIt&);    // is not implemented, ergo, is
  193.                     // not allowed
  194.  
  195.   IMAGE& median_3_row(void);        // 3-point row-wise filtration
  196.   IMAGE& median_3_col(void);        // 3-point col-wise filtration
  197.   IMAGE& median_5_row(void);        // 5-point row-wise filtration
  198.   IMAGE& median_5_col(void);        // 5-point col-wise filtration
  199. public:
  200.   
  201.                 // How to apply filters
  202.   enum Direction { Columns, Rows, RowsAndColumns };
  203.  
  204.   FilterIt(IMAGE& _image) : image(_image) {}
  205.  
  206.   IMAGE& median(const Direction how, const int win_size = 3);
  207.  
  208.                 // Convolution methods
  209.                 // Templates don't work inside the class 8:(
  210.                 // ("method templates" would do, by they
  211.                 // aren't supported yet)
  212. #define CONV_DECL(Kernel,Denom)                \
  213.   IMAGE& conv_row(const Kernel<Denom>& kernel);        \
  214.   IMAGE& conv_col(const Kernel<Denom>& kernel);        \
  215.   IMAGE& conv(const Kernel<Denom>& kernel,        \
  216.           const Direction how = RowsAndColumns);    \
  217.  
  218.   CONV_DECL(ConvKernel3,CommonDenomOne)
  219.   CONV_DECL(ConvKernel3,over_2_up)
  220.   CONV_DECL(ConvKernel3,CommonDenom)
  221.  
  222. #undef CONV_DECL
  223.  
  224.                 // Translate image pixels according to
  225.                 // the look-up table
  226.   IMAGE& translate(const LookupT& lookupt,
  227.            const LookupT::FringeHandling fringe_handling);
  228. };
  229.  
  230. #endif
  231.